/**
 * 动态文字精灵
 *
 * 用法：
 *   1.创建精灵材质
 *   const text = new DynamicTextSprite(container, content,position, options)
 *   2.更新内容
 *   text.updateContent(content)
 */

import * as THREE from 'three';

type DynamicTextSpriteOption = {
  size?: number;
  backgroundImageUrl?: string;
  backgroundColor?: string;
  textAlign?: CanvasTextAlign;
  paddingLeft?: number;
  paddingTop?: number;
  width?: number;
  height?: number;
  fontSize?: number;
  fontSizes?: number[];
  labelName?: string;
};

export default class DynamicTextSprite {
  backgroundImageUrl: string = '';
  backgroundColor: string = 'rgba(255,255,255,1)';
  img = new Image();
  canvas = document.createElement('canvas');
  label!: THREE.Sprite;
  isAttenuation = false;
  boxWidth = 150;
  boxHeight = 70;
  paddingTop = 0;
  fontSize = 16;
  // 此参数是考虑到多行显示且字体不一样时使用,且要根据显示行数给字体大小参数
  fontSizes: number[] = [];
  lineHeight = 1.5;
  canvasTexture: THREE.CanvasTexture | null = null;
  options: { textAlign: CanvasTextAlign; paddingLeft: number } = {
    textAlign: 'center',
    paddingLeft: 0,
  };

  constructor(
    container: THREE.Group,
    content: string[],
    position: [number, number, number],
    isAttenuation: boolean,
    options?: DynamicTextSpriteOption
  ) {
    this.isAttenuation = isAttenuation;
    if (options) {
      if (options.backgroundImageUrl != null)
        this.backgroundImageUrl = options.backgroundImageUrl;
      if (options.backgroundColor != null)
        this.backgroundColor = options.backgroundColor;
      if (options.textAlign != null) this.options.textAlign = options.textAlign;
      if (options.paddingLeft != null)
        this.options.paddingLeft = options.paddingLeft;
      if (options.paddingTop != null) this.paddingTop = options.paddingTop;
      if (options.width != null) this.boxWidth = options.width;
      if (options.height != null) this.boxHeight = options.height;
      if (options.fontSize != null) this.fontSize = options.fontSize;
      if (options.fontSizes != null) this.fontSizes = options.fontSizes;
    }

    // 有无背景图片
    if (this.backgroundImageUrl) {
      this.img.src = this.backgroundImageUrl;
      this.img.onload = () => {
        this.label = this.addSprite(content)!;
        if (this.label) {
          this.label.position.set(position[0], position[1], position[2]);
          container.add(this.label);
          this.label.name = options?.labelName || '';
        }
      };
    } else {
      this.label = this.addSprite(content)!;
      if (this.label) {
        this.label.position.set(position[0], position[1], position[2]);
        container.add(this.label);
        this.label.name = options?.labelName || '';
      }
    }
  }

  // 创建标签画布
  createLabelCanvas(baseWidth: number, lines: string[]) {
    const ctx = this.canvas.getContext('2d');
    const font = `${this.fontSize}px bold sans-serif`;
    const lineHeightPx = this.fontSize * this.lineHeight;

    if (ctx) {
      const width = baseWidth;
      // console.log(this.fontSize, width, height);

      ctx.canvas.width = width;
      ctx.canvas.height = this.boxHeight;
      ctx.font = font;
      ctx.textBaseline = 'middle';
      ctx.fillStyle = this.backgroundColor; // 设置背景色
      ctx.fillRect(0, 0, width, this.boxHeight);
      ctx.drawImage(this.img, 0, 0, width, this.boxHeight);
      ctx.fillStyle = 'white';

      ctx.textBaseline = 'top';

      ctx.textAlign = this.options.textAlign;
      let x = 0;
      if (ctx.textAlign == 'left') {
        x = 0;
      } else if (ctx.textAlign == 'center') {
        x = width / 2;
      } else if (ctx.textAlign == 'right') {
        x = width;
      }
      // 文字基于容器显示位置
      for (let i = 0; i < lines.length; i++) {
        if (this.fontSizes.length > 0) {
          const font = `${this.fontSizes[i]}px bold sans-serif`;
          ctx.font = font;
        }

        ctx.fillText(
          lines[i],
          x + this.options.paddingLeft,
          this.paddingTop + i * lineHeightPx
        );
      }
      return ctx.canvas;
    } else {
      return null;
    }
  }

  // 创建精灵文字

  addSprite(name: string[]) {
    const canvas = this.createLabelCanvas(this.boxWidth, name);

    this.canvasTexture = new THREE.CanvasTexture(canvas!);
    // console.log('this.canvasTexture', this.canvasTexture);

    this.canvasTexture.minFilter = THREE.LinearFilter;
    this.canvasTexture.wrapS = THREE.ClampToEdgeWrapping;
    this.canvasTexture.wrapT = THREE.ClampToEdgeWrapping;
    const labelMaterial = new THREE.SpriteMaterial({
      map: this.canvasTexture,
    });
    labelMaterial.sizeAttenuation = this.isAttenuation;
    // labelMaterial.depthTest = false;
    const label = new THREE.Sprite(labelMaterial);
    // label.position.z = this.textBoxWidth;
    const labelBaseScale = 0.0013;
    if (canvas) {
      label.scale.x = canvas.width * labelBaseScale;
      label.scale.y = canvas.height * labelBaseScale;
      return label;
    } else {
      return null;
    }
  }
  
  // 更新内容
  updateContent(content: string[], imgUrl?: string) {
    if (this.label && this.canvasTexture) {
      // 直接更新现有的CanvasTexture的内容
      if (imgUrl) {
        this.img.src = imgUrl;
        this.img.onload = () => {
          if (this.canvasTexture) {
            const updatedCanvas = this.createLabelCanvas(
              this.boxWidth,
              content
            );
            if (updatedCanvas) {
              this.updateCanvasTexture(updatedCanvas);
            }
          }
        };
      } else {
        const updatedCanvas = this.createLabelCanvas(this.boxWidth, content);
        if (updatedCanvas) {
          this.updateCanvasTexture(updatedCanvas);
        }
      }
    }
  }

  updateCanvasTexture(updatedCanvas: HTMLCanvasElement) {
    if (this.canvasTexture && updatedCanvas) {
      this.canvasTexture.image = updatedCanvas;
      this.canvasTexture.needsUpdate = true; // 标记为需要更新
    }
  }
}
